package com.adhere.security.aspect;

import com.adhere.security.annotation.RequirePermissions;
import com.adhere.security.utils.AuthUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 前置授权切面
 * 主要实现的逻辑为：
 * 当方法或类被 RequirePermissions 注解修饰时，需要验证当前登录用户是否访问此类或者方法的权限
 *
 * @author WT
 * @date 2022/02/09 14:50:40
 */
@Aspect
@Component
public class AuthorizationAspect {

    /**
     * 指定切入点,定义 Advice 要发生的地方为被 @RequirePermissions 修饰的方法
     */
    @Pointcut("@annotation(com.adhere.security.annotation.RequirePermissions)")
    public void pointcut() {
    }

    /**
     * 环绕切入
     *
     * @param joinPoint 切面对象
     * @return 底层方法执行后的返回值
     * @throws Throwable 底层方法抛出的异常
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {

        // 获取被标记的方法或者类对象
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        checkMethodPermissions(signature.getMethod());
        // 执行原有逻辑
        return joinPoint.proceed();

    }

    /**
     * 对一个Method对象进行注解检查
     */
    public void checkMethodPermissions(Method method) {

        // 校验 @RequiresPermissions 注解
        RequirePermissions requirePermissions = method.getAnnotation(RequirePermissions.class);
        if (requirePermissions != null) {
            AuthUtils.checkPermi(requirePermissions);
        }

    }


}
